/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package geneontofx.statistics;

import geneontofx.math.Binomial;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

/**
 *
 * @author loskov
 */
public class PValue {
    
    private static final MathContext MATH_CONTEXT = new MathContext(16, RoundingMode.CEILING);
    private BigDecimal result;

    public PValue() {
        
    }
    
    public BigDecimal pValue(Integer N, Integer m, Integer n, Integer x) {
        /*
         * N - population size
         * m - study size
         * n - (current GO) population count
         * x - (current GO) group count
         */
        result = new BigDecimal(0);
        for(Integer i = x; i <= n; i++) {
            Integer intNm = N - m;
            Integer intnx = n - i;
            
            BigDecimal upperFirst = new Binomial().binomialDecimal(m, i);
            BigDecimal upperSecond = new Binomial().binomialDecimal(intNm, intnx);
            BigDecimal lower = new Binomial().binomialDecimal(N, n);
            BigDecimal current = upperFirst.multiply(upperSecond);
            current = current.divide(lower, MATH_CONTEXT);
            
            result = result.add(current);
        }
        return result;
    }
    
    public BigDecimal pValueLog(Integer N, Integer m, Integer n, Integer x) {
        /*
         * N - population size
         * m - study size
         * n - (current GO) population count
         * x - (current GO) study count
         */
        result = new BigDecimal(0);
        for(Integer i = x; i <= n; i++) {
            Integer intNm = N - m;
            Integer intnx = n - i;
            
            BigDecimal upperFirst = new Binomial().binomialLog(m, i);
            BigDecimal upperSecond = new Binomial().binomialLog(intNm, intnx);
            BigDecimal lower = new Binomial().binomialLog(N, n);
            BigDecimal currentVal = upperFirst.add(upperSecond).subtract(lower);
            
            double exp = Math.exp(currentVal.doubleValue());
            
            result = result.add(new BigDecimal(exp));
            
        }
        return result;
    }

    public BigDecimal getResult() {
        return result;
    }
}
